<template>
  <div class="address-container">
    <!-- 地址展示 -->
    <el-tooltip
      :content="modelValue?.address"
      :disabled="!showTooltip"
      placement="top"
    >
      <el-text class="address-text" truncated @click="openMapDialog">
        {{ modelValue?.address }}
      </el-text>
    </el-tooltip>

    <!-- 地图弹窗 -->
    <el-dialog
      v-model="dialogVisible"
      title="位置详情"
      width="60%"
      height="80%"
      @closed="destroyMap"
      :append-to-body="true"
      teleported
    >
      <div class="map-content">
        <div v-if="loading" class="map-loading">地图加载中...</div>
        <div ref="mapContainer" class="map-wrapper"></div>

        <!-- 信息展示 -->
        <div class="position-info mt-4">
          <el-descriptions :column="1" border>
            <el-descriptions-item label="地址">{{
              modelValue.address
            }}</el-descriptions-item>
            <el-descriptions-item label="经度">{{
              modelValue.lng
            }}</el-descriptions-item>
            <el-descriptions-item label="纬度">{{
              modelValue.lat
            }}</el-descriptions-item>
          </el-descriptions>
        </div>

        <div class="dialog-footer mt-4">
          <el-button type="primary" @click="dialogVisible = false"
            >确定</el-button
          >
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
/**
 * 百度地址展示组件
 * 经纬度格式：BD09
 * @param {Object} modelValue - 绑定的坐标对象
 * @param {number} modelValue.lng - 经度
 * @param {number} modelValue.lat - 纬度
 * @param {string} modelValue.address - 地址
 */
import { ref, computed, watch, nextTick } from 'vue';
import { ElMessage } from 'element-plus';

const ak = import.meta.env.VITE_APP_MAP_BMAP_AK; // 百度地图密钥

const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({
      address: '',
      lng: null,
      lat: null,
    }),
  },
});

const emit = defineEmits(['update:modelValue']);

// 响应式状态
const dialogVisible = ref(false);
const loading = ref(false);
const mapInstance = ref(null);
const mapContainer = ref(null);

const showTooltip = computed(
  () =>
    props.modelValue &&
    props.modelValue.address &&
    props.modelValue.address.length > 20,
);

// 动态加载百度地图API
const loadBMap = () => {
  return new Promise((resolve) => {
    if (window.BMapGL) return resolve();

    window.BMapGL_loadScriptTime = Date.now();
    window.BMapGL = {};
    window.BMapGL.callback = resolve;

    const script = document.createElement('script');
    script.src = `https://api.map.baidu.com/api?type=webgl&v=1.0&ak=${ak}&callback=BMapGL.callback`;
    document.head.appendChild(script);
  });
};

// 初始化地图
const initMap = async () => {
  try {
    loading.value = true;
    await loadBMap();

    mapInstance.value = new BMapGL.Map(mapContainer.value, {
      enableMapClick: false,
    });

    const point = new BMapGL.Point(props.modelValue.lng, props.modelValue.lat);

    mapInstance.value.centerAndZoom(point, 16);
    mapInstance.value.enableScrollWheelZoom(true);

    // 添加标记
    const marker = new BMapGL.Marker(point);
    mapInstance.value.addOverlay(marker);

    // 添加信息窗口
    const infoWindow = new BMapGL.InfoWindow(props.modelValue.address);
    marker.addEventListener('click', () => {
      marker.openInfoWindow(infoWindow);
    });
  } catch (error) {
    ElMessage.error('地图初始化失败');
  } finally {
    loading.value = false;
  }
};

// 打开弹窗
const openMapDialog = async () => {
  if (!validateCoordinates()) {
    return ElMessage.warning('无效的坐标信息');
  }

  dialogVisible.value = true;
  nextTick(async () => {
    if (!mapInstance.value) await initMap();
  });
};

// 坐标验证
const validateCoordinates = () => {
  const { lng, lat } = props.modelValue;
  return lng && lat && Math.abs(lng) <= 180 && Math.abs(lat) <= 90;
};

// 销毁地图
const destroyMap = () => {
  if (mapInstance.value) {
    mapInstance.value.destroy();
    mapInstance.value = null;
  }
};

// 监听坐标变化更新地图
watch(
  () => props.modelValue,
  () => {
    if (mapInstance.value && validateCoordinates()) {
      const point = new BMapGL.Point(
        props.modelValue.lng,
        props.modelValue.lat,
      );
      mapInstance.value.panTo(point);
    }
  },
);
</script>

<style scoped>
.address-container {
  cursor: pointer;
  display: inline-block;
  max-width: 400px;
}

.address-text {
  color: var(--el-color-primary);
  transition: color 0.3s;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.address-text:hover {
  color: var(--el-color-primary-light-3);
  text-decoration: underline;
}

.map-content {
  position: relative;
  height: 70vh;
}

.map-wrapper {
  height: 500px;
  width: 100%;
  border-radius: 4px;
  overflow: hidden;
}

.map-loading {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.position-info {
  background: var(--el-fill-color-light);
  padding: 12px;
  border-radius: 4px;
}

.dialog-footer {
  text-align: right;
}
</style>
